import os
import unittest
import nose
from limber import componentmanager
from tests.mocks import *
from tests.tools import ConnectionBox


def setup_module():
    set_mockdir(0)

def testInstantiate():
    parent = MockApplication()
    componentmanager.ComponentManager(parent)


class TestComponentManager(unittest.TestCase):
    def setUp(self):
        self.parent = MockApplication()
        self.manager = componentmanager.ComponentManager(self.parent)

    def testComponentsLoading(self):
        self.manager.load_components()
        self.assertEqual(self.manager.number_of_components(), 4)

        names = (
            'mock-plain-text-document',
            'mock_plain_text_document',
            'mock_html_text_document',
            'mock_text_view')
        for name in names:
            self.assertTrue(self.manager.has_component(name))

        self.assertEqual(tuple(sorted(self.manager.components_names())),
                         tuple(sorted(names)))

    def testEmitsSignals(self):
        box = ConnectionBox()
        self.manager.component_registered.connect(box.slot)
        self.manager.load_components()

        self.assertEqual(box.signals_arrived, 4)

    def testLoadsRightComponents(self):
        import sys
        sys.path.insert(0, os.path.join(self.parent.userdir_path(), 'Widgets'))
        from mock_plain_text_document import MockPlainTextDocument
        sys.path.pop(0)

        sys.path.insert(0, os.path.join(self.parent.systemdir_path(), 'Widgets'))
        from mock_plain_text_document2 import MockPlainTextDocument2
        from mock_html_text_document import MockHtmlTextDocument
        from mock_text_view import MockTextView
        sys.path.pop(0)

        self.manager.load_components()
        self.assertEqual(self.manager.component('mock-plain-text-document'),
                         MockPlainTextDocument)
        self.assertEqual(self.manager.component('mock_plain_text_document'),
                         MockPlainTextDocument2)
        self.assertEqual(self.manager.component('mock_html_text_document'),
                         MockHtmlTextDocument)
        self.assertEqual(self.manager.component('mock_text_view'),
                         MockTextView)

    def testComponent(self):
        self.manager.load_components()
        self.assertTrue(bool(self.manager.component('mock-plain-text-document')))
        self.assertRaises(componentmanager.ComponentManagerError,
                          self.manager.component, 'Non-existent component.')

    def testGetDocument(self):
        MockPlainTextDocument = mock_components(0)[0]

        self.manager.load_components()
        doc_class = self.manager.get_document('mock-plain-text-document')
        self.assertEqual(doc_class, MockPlainTextDocument)

        self.assertRaises(componentmanager.ComponentManagerError,
                          self.manager.get_document, 'mock_text_view')
        self.assertRaises(componentmanager.ComponentManagerError,
                          self.manager.get_document, 'Non-existent component.')

    def testGetView(self):
        MockTextView = mock_components(1)[0]

        self.manager.load_components()
        view_class = self.manager.get_view('mock_text_view')
        self.assertEqual(view_class, MockTextView)

        self.assertRaises(componentmanager.ComponentManagerError,
                          self.manager.get_view, 'mock-plain-text-document')
        self.assertRaises(componentmanager.ComponentManagerError,
                          self.manager.get_view, 'Non-existent component.')

    def testGetViewDisplay(self):
        set_mockdir(1)

        MockTabViewDisplay = mock_components(0)[0]

        parent = MockApplication()
        manager = componentmanager.ComponentManager(parent)
        manager.load_components()

        viewdisplay_class = manager.get_viewdisplayer('mock_tab_view_display')
        self.assertEqual(viewdisplay_class, MockTabViewDisplay)

        self.assertRaises(componentmanager.ComponentManagerError,
                          manager.get_viewdisplayer, 'mock_image_document')
        self.assertRaises(componentmanager.ComponentManagerError,
                          manager.get_viewdisplayer, 'Non-existent component.')

        set_mockdir(0)
    
    def testLoadBuiltInComponents(self):
        self.manager.load_builtin_components()
        
        self.assertTrue(self.manager.has_component('basetextview'))
        self.assertTrue(self.manager.has_component('basetextdocument'))
        self.assertTrue(self.manager.has_component('tabbedviewdisplayer'))
    
    def testComponentsNamesByInterface(self):
        components = (
            MockGenericObject(name='test1', interface='document',
                              version='0.1.0', abilities='TEXT'), 
            MockGenericObject(name='test2', interface='view', 
                              version='0.1.0rc', abilities='TEXT:HTML_TEXT'), 
            MockGenericObject(name='test3', interface='viewdisplayer', 
                              version='1.2.1', abilities='TEXT'), 
            MockGenericObject(name='test4', interface='document', 
                              version='0.1.1', abilities='BINARY:IMAGE_BINARY'), 
            )
        
        self.manager.register_components((comp.name for comp in components), components)
        doc_names = self.manager.components_names_by_interface('document')
        view_names = self.manager.components_names_by_interface('view')
        viewdisplayer_names = self.manager.components_names_by_interface('viewdisplayer')
        
        self.assertEqual(sorted(doc_names), ['test1', 'test4'])
        self.assertEqual(sorted(view_names), ['test2'])
        self.assertEqual(sorted(viewdisplayer_names), ['test3'])
        
